package com.htudata.core.util.operation;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

public class DateTimeOperationUtils {

  public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
  
  public static final String YYYYMMDDHHMM = "yyyyMMddHHmm";
  
  public static final String YYYYMMDDHH = "yyyyMMddHH";
  
  public static final String YYYYMMDD = "yyyyMMdd";
  
  public static final String YYYYMM = "yyyyMM";
  
  public static final String YYYY = "yyyy";
  
  public static final String DATETIMEFORMAT = "yyyy-MM-dd HH:mm:ss";
  
  public static final String DATETIMEFORMAT2 = "yyyy-MM-dd";
  
  public static final String DATETIMEFORMAT3 = "yyyy-MM";
  
  public static final String DATETIMEFORMAT4 = "HH:mm:ss";
  
  public static final String DATETIMEFORMAT5 = "HH:mm";
  
  public static final String DATETIMEFORMAT6 = "yyyyMMdd HH:mm:ss";
  
  public static final int SECOND_VALUE = 1000;
  
  public static final int MINUE_VALUE = 60000;
  
  public static final int HOUR_VALUE = 3600000;
  
  public static final int DAY_VALUE = 86400000;
  
  public static final JSONArray TIME_STAMP_INFOS = new JSONArray();
  
  public static final JSONArray TIME_STAMP_INFOS_NEW = new JSONArray();
  
  static {
    JSONObject map = new JSONObject();
    map.put("name", "mon");
    map.put("value", Long.valueOf(2592000L));
    TIME_STAMP_INFOS.add(map);
    map = new JSONObject();
    map = new JSONObject();
    map.put("name", "d");
    map.put("value", Long.valueOf(86400L));
    TIME_STAMP_INFOS.add(map);
    map = new JSONObject();
    map.put("name", "h");
    map.put("value", Long.valueOf(3600L));
    TIME_STAMP_INFOS.add(map);
    map = new JSONObject();
    map.put("name", "m");
    map.put("value", Long.valueOf(60L));
    TIME_STAMP_INFOS.add(map);
    map = new JSONObject();
    map.put("name", "s");
    map.put("value", Long.valueOf(1L));
    TIME_STAMP_INFOS.add(map);
    JSONObject map1 = new JSONObject();
    map1.put("name", "月");
    map1.put("value", Long.valueOf(2592000L));
    TIME_STAMP_INFOS_NEW.add(map1);
    map1 = new JSONObject();
    map1 = new JSONObject();
    map1.put("name", "天");
    map1.put("value", Long.valueOf(86400L));
    TIME_STAMP_INFOS_NEW.add(map1);
    map1 = new JSONObject();
    map1.put("name", "小时");
    map1.put("value", Long.valueOf(3600L));
    TIME_STAMP_INFOS_NEW.add(map1);
    map1 = new JSONObject();
    map1.put("name", "分钟");
    map1.put("value", Long.valueOf(60L));
    TIME_STAMP_INFOS_NEW.add(map1);
    map1 = new JSONObject();
    map1.put("name", "秒");
    map1.put("value", Long.valueOf(1L));
    TIME_STAMP_INFOS_NEW.add(map1);
  }

  public static Date parse(String dateTime, String dateTimeFormat) throws Exception {
    try {
      return (new SimpleDateFormat(dateTimeFormat)).parse(dateTime);
    } catch (ParseException e) {
       throw e;
    } 
  }
  
  public static LocalDateTime parseToLocalDateTime(String localDateTime, String dateTimeFormat) {
    try {
      DateTimeFormatter format = DateTimeFormatter.ofPattern(dateTimeFormat);
      return LocalDateTime.parse(localDateTime, format);
    } catch (Exception e) {
      throw e;
    } 
  }
  
  public static Date getUTCDate(Date bjDate) {
    return getBeforeOrAfterDate(bjDate, 11, -8);
  }
  
  public static Date getBeiJingDate(Date utcDate) {
    return getBeforeOrAfterDate(utcDate, 11, 8);
  }
  
  public static Date getDateByTimeInMillis(long timeInMillis) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(timeInMillis);
    Date result = calendar.getTime();
    return result;
  }
  
  public static Date getAnyHourDate(Date date, int hour) throws Exception {
    return parse(format(date, "yyyyMMdd") + hour, "yyyyMMddHH");
  }
  
  public static Date getBeforeOrAfterDate(Date date, int dateTimeType, int off) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    calendar.add(dateTimeType, off);
    Date result = calendar.getTime();
    return result;
  }
  
  public static Date getNextMonday(Date date) {
    int mondayPlus = getMinusDaybetweenNowAndSunday(date);
    GregorianCalendar currentDate = new GregorianCalendar();
    currentDate.add(5, mondayPlus + 7);
    Date result = currentDate.getTime();
    return result;
  }
  
  public static long getMinusDateTimeValue(Date beginDate, Date endDate, int dateTimeValue) {
    return getDateTimeValueByTimeInMillis(endDate.getTime() - beginDate.getTime(), dateTimeValue);
  }
  
  public static long getDateTimeValueByTimeInMillis(long timeInMillis, int dateTimeValue) {
    long result = timeInMillis / dateTimeValue;
    return result;
  }
  
  public static String format(Date date, String dateTimeFormat) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    String result = (new SimpleDateFormat(dateTimeFormat)).format(calendar.getTime());
    return result;
  }
  
  public static String format(LocalDateTime localDateTime, String dateTimeFormat) {
    DateTimeFormatter df = DateTimeFormatter.ofPattern(dateTimeFormat);
    String result = df.format(localDateTime);
    return result;
  }
  
  public static String getBeforeOrAfterDateTime(String dateTime, String dateTimeFormat, int dateTimeType, int off) throws Exception {
    return format(getBeforeOrAfterDate(parse(dateTime, dateTimeFormat), dateTimeType, off), dateTimeFormat);
  }
  
  public static String changeDateTimeFormat(String dateTime, String srcDateTimeFormat, String tgtDateTimeFormat) throws Exception {
    SimpleDateFormat simpledateformat = new SimpleDateFormat(srcDateTimeFormat);
    Date date = null;
    try {
      date = simpledateformat.parse(dateTime);
    } catch (ParseException e) {
      throw e;
    } 
    simpledateformat.applyPattern(tgtDateTimeFormat);
    String result = simpledateformat.format(date);
    return result;
  }
  
  public static String getDateTimeByMinuteMultiple(int minuteMultiple) {
    Date date = new Date();
    if (minuteMultiple == 0)
      return format(date, "yyyyMMddHH0000"); 
    int minute = Integer.parseInt(format(date, "mm"));
    int minuteNew = minute / minuteMultiple * minuteMultiple;
    String result = format(date, "yyyyMMddHH");
    if (minuteNew < 10)
      result = result + "0"; 
    result = result + minuteNew;
    result = result + "00";
    return result;
  }
  
  public static String getDayOfWeek(Date date) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    return getDayOfWeek(calendar.get(7));
  }
  
  public static String getDayOfWeek(int dayOfWeek) {
    String result = null;
    switch (dayOfWeek) {
      case 1:
        result = "日";
        break;
      case 2:
        result = "一";
        break;
      case 3:
        result = "二";
        break;
      case 4:
        result = "三";
        break;
      case 5:
        result = "四";
        break;
      case 6:
        result = "五";
        break;
      case 7:
        result = "六";
        break;
    } 
    return result;
  }
  
  public static int getEndDayOfMonth(Date date) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    int result = calendar.getActualMaximum(5);
    return result;
  }
  
  private static int getMinusDaybetweenNowAndSunday(Date date) {
    Calendar cd = Calendar.getInstance();
    cd.setTime(date);
    int dayOfWeek = cd.get(7) - 1;
    if (dayOfWeek == 1)
      return 0; 
    int result = 1 - dayOfWeek;
    return result;
  }
  
  public static boolean isAfter(Date date1, Date date2) {
    long time1 = date1.getTime();
    long time2 = date2.getTime();
    if (time1 > time2)
      return true; 
    return false;
  }
  
  public static boolean isEndDayOfMonth(Date date) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    Calendar tempCalendar = (Calendar)calendar.clone();
    calendar.add(5, 1);
    if (calendar.get(2) != tempCalendar.get(2))
      return true; 
    return false;
  }
  
  public static String timeStampToString(long timeStamp, int expectedUnitCount) {
    StringBuffer result = new StringBuffer();
    JSONObject timeStampInfo = null;
    int unitCount = 0;
    for (int i = 0, length = TIME_STAMP_INFOS.size(), last = length - 1; i < length; i++) {
      timeStampInfo = (JSONObject)TIME_STAMP_INFOS.get(i);
      long value = timeStamp / timeStampInfo.getLongValue("value");
      if (value != 0L) {
        result.append(value + timeStampInfo.getString("name"));
        unitCount++;
        if (expectedUnitCount > 0 && unitCount == expectedUnitCount)
          break; 
        if (i < last)
          result.append(" "); 
      } 
      timeStamp %= timeStampInfo.getLongValue("value");
      if (timeStamp == 0L)
        break; 
    } 
    return result.toString();
  }
  
  public static String timeStampToStringNew(long timeStamp, int expectedUnitCount) {
    StringBuffer result = new StringBuffer();
    JSONObject timeStampInfo = null;
    int unitCount = 0;
    for (int i = 0, length = TIME_STAMP_INFOS_NEW.size(), last = length - 1; i < length; i++) {
      timeStampInfo = (JSONObject)TIME_STAMP_INFOS_NEW.get(i);
      long value = timeStamp / timeStampInfo.getLongValue("value");
      if (value != 0L) {
        result.append(value + timeStampInfo.getString("name"));
        unitCount++;
        if (expectedUnitCount > 0 && unitCount == expectedUnitCount)
          break; 
      } 
      timeStamp %= timeStampInfo.getLongValue("value");
      if (timeStamp == 0L)
        break; 
    } 
    return result.toString();
  }
  
  public static List<String> getTimeStringForInteMinute(Date date, int hour, String format) {
    List<String> timelist = new ArrayList<>();
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    for (int i = 0; i <= hour; i++) {
      timelist.add(format(calendar.getTime(), format));
      calendar.add(12, -1);
    } 
    return timelist;
  }
  
  public static List<String> getTimeStringForInteSecond(Date date, int hour, String format) {
    List<String> timelist = new ArrayList<>();
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    for (int i = 0; i <= hour; i++) {
      timelist.add(format(calendar.getTime(), format));
      calendar.add(13, -1);
    } 
    return timelist;
  }
}
